//
//  SystemDatabase.cpp
//  Phidgets
//
//  Created by Daniel Hazelbaker on 11/19/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <iostream>
#include <stdexcept>
#include "SystemDatabase.h"



SystemDatabase *gSharedDatabase = NULL;


//
// Create a new system database.
//
SystemDatabase::SystemDatabase(std::string dbPath)
{
    if (sqlite3_open(dbPath.c_str(), &_database) != 0)
    {
        sqlite3_close(_database);
        _database = NULL;
        
        throw std::runtime_error("Could not open system database.");
    }
    
	//
	// Initialize the mutexes.
	//
    pthread_mutexattr_init(&_lockMutexAttr);
    pthread_mutexattr_settype(&_lockMutexAttr, PTHREAD_MUTEX_RECURSIVE);
	pthread_mutex_init(&_lockMutex, &_lockMutexAttr);

    PrepareDatabase();
}


//
// Close the database when this object is deleted.
//
SystemDatabase::~SystemDatabase()
{
    if (_database != NULL)
    {
        sqlite3_close(_database);
        _database = NULL;
        
        pthread_mutex_destroy(&_lockMutex);
        pthread_mutexattr_destroy(&_lockMutexAttr);
    }
}


//
// Prepare the database for use, create all initial values.
//
void SystemDatabase::PrepareDatabase()
{
    if (TableExists("scripts") == false)
    {
        ExecuteSimpleNonQuery("CREATE TABLE scripts(script_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, runtype INTEGER NOT NULL, code TEXT NOT NULL)");
    }
}


//
// Execute a simple query (e.g. CREATE TABLE).
//
bool SystemDatabase::ExecuteSimpleNonQuery(std::string sql)
{
    return (sqlite3_exec(_database, sql.c_str(), NULL, NULL, NULL) == SQLITE_OK);
}


//
// Prepare a new SQL statement to run against this database.
//
SqlStatement *SystemDatabase::prepareStatement(std::string sql, SqlParameters params)
{
    return new SqlStatement(this, _database, sql, params);
}


//
// Check if the table exists in the database.
//
bool SystemDatabase::TableExists(std::string tableName)
{
    SqlStatement *stmt;
    SqlParameters params = SqlParameters();
    bool status = false;
    
    
    params["@Name"] = tableName;
    stmt = prepareStatement("SELECT name FROM sqlite_master WHERE type='table' AND name=@Name", params);
    status = !stmt->ExecuteScalar().isNull();
    delete stmt;

    return status;
}


//
// Retrieve the last insert row id.
//
unsigned long SystemDatabase::LastInsertRowID() const
{
    return sqlite3_last_insert_rowid(_database);
}


